package com.feib.ebilling.job;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import org.springframework.stereotype.Service;
import com.enterprisedt.net.ftp.FileTransferClient;
import com.feib.ebilling.job.dao.BankingFeedbackDao;
import com.feib.ebilling.job.util.StringUtils;


/**
 * @title (#)P0028Import.java<br>
 * @description 匯入P0028查詢檔案<br>
 * @author Yaude Huang<br>
 * @version 1.0.0 2011/11/18
 * @copyright Far Eastern International Bank Copyright (c) 2011<br>
 * @2011/11/09 create by Yaude Huang<br>
 */


@Service("p0028Import")
public class P0028Import {
	public static Logger logger = LoggerFactory.getLogger(P0028Import.class);
	
	private static final int BUFFER_SIZE1 = 161;
	private static final int BUFFER_SIZE2 = 151;
	
	public static final SimpleDateFormat BASIC_DATE_TIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

	@Resource(name="ftpProperties")
    private Properties ftpProperties;
	
	@Resource(name="bankingFeedbackDao")
	private BankingFeedbackDao bankingFeedbackDao;
	
	private String processDate = "";
	
	public static Map<String, String> CHANEL_CODE = new HashMap<String, String>();
    
	public static void main(String[] args) {
		
		ApplicationContext ctx = new ClassPathXmlApplicationContext(
				new String[] { "applicationContext-config.xml",	"applicationContext-dao.xml",
							   "applicationContext-properties.xml" });

		Date start = new Date();
		logger.info("[開始] 匯入P0028查詢資料  - {}",	BASIC_DATE_TIME_FORMAT.format(start));
		try {
			P0028Import p0028Import = (P0028Import) ctx.getBean("p0028Import");
			/* 匯入資料 */
			p0028Import.getFiles("FEIB", "DMPAYMR.DAT");
			p0028Import.getFiles("FEIB", "DMPAYDTLM.DAT");
			/* 寫入資料有效日期 */            
            p0028Import.updateP0028Date();
		} catch (Exception e) {
			logger.error("[錯誤]" + e.getMessage(), e);
		} finally {
			Date end = new Date();
			logger.info("[結束] 匯入P0028查詢資料 - {}", BASIC_DATE_TIME_FORMAT.format(start));
			logger.info("共費時 - " + ((end.getTime() - start.getTime()) / 1000) + " 秒");
		}
	}
	
	public void updateP0028Date()
    {
		if (processDate.equals("")){
			/* 前一日非營業日取不到檔案 */
			logger.info("P0028 query valid date not changed");
		}else{
			logger.info("{} P0028 query valid date changed", processDate);
			this.bankingFeedbackDao.updateP0028_Date(processDate);         
		}
    }
	
	public void getFiles(String sChanel, String FileName)
    {
        FileTransferClient ftp = null;
        /* 取得FTP設定 */
        String host  = ftpProperties.getProperty(sChanel + "#FTPServerIP");
        String username = ftpProperties.getProperty(sChanel + "#FTPUserName");
        String password = ftpProperties.getProperty(sChanel + "#FTPPassword");
        String localFolder = ftpProperties.getProperty(sChanel + "#LocalFolder");
        String remoteFolder = ftpProperties.getProperty(sChanel + "#RemoteFolder");
        
        logger.info("FTP Server Connect : {}", host);
        logger.info("FTP User Name : {}", username);
        logger.info("FTP Local Directory : {}", localFolder);
        logger.info("FTP Remote Directory : {}", remoteFolder);
        
        
        try {
            ftp = new FileTransferClient();
            ftp.setRemoteHost(host);
            ftp.setUserName(username);
            ftp.setPassword(password); 
            ftp.connect();
            if (ftp.isConnected()){

                /* 切換FTP目錄  */
                if (remoteFolder != null && !remoteFolder.trim().equals("")){
                    ftp.changeDirectory(remoteFolder);
                    logger.info("Directory change to {}", ftp.getRemoteDirectory());
                }
                
                /* 下載檔案 */ 
                logger.info("File {} size is {} Bytes", FileName, ftp.getSize(FileName));
                ftp.downloadFile(localFolder, FileName);  
                logger.info("{} is download", FileName);
                ftp.disconnect();
                logger.info("{} is disconnect", host);
                
                /* 檔案轉換 EBCDIC2Big5 */
                int exitVal = 0;
                logger.info("Convert File start : " + new Date(System.currentTimeMillis()));
			    Runtime oRun = Runtime.getRuntime();			   
			    Process oProcess = oRun.exec(localFolder + "\\convert.bat " + FileName + " " + FileName + ".bg");			    
			    BufferedReader input = new BufferedReader(new InputStreamReader(oProcess.getInputStream()));
			    String line = null; 
                while((line = input.readLine()) != null) {
                	 logger.info(line);
                }
			    try {
                     exitVal = oProcess.waitFor();
                     logger.info("Exited with error code : " + exitVal);
			    } catch(Exception e) {
			    	 logger.error(e.toString());			    	 
	            }
			    logger.info("Convert File end : " + new Date(System.currentTimeMillis()));
			   
                /* 開啟檔案 */
			    if (exitVal == 0){ 
	                long total = 0;
	                int BUFFER_SIZE = 0;
	                String str = "";
	                if (FileName.equals("DMPAYMR.DAT")) BUFFER_SIZE = BUFFER_SIZE1;
	                if (FileName.equals("DMPAYDTLM.DAT")) BUFFER_SIZE = BUFFER_SIZE2;
				        								   
	            	BufferedInputStream in = new BufferedInputStream(new FileInputStream(localFolder + "\\" + FileName + ".bg"));
	                byte[] buffer = new byte[BUFFER_SIZE];
	                try {
	                    int n = in.read(buffer, 0, BUFFER_SIZE);                            
	                    while (n >= 0) {
	                    	str = new String(buffer, "Big5");
	                        Map<String, Object> map = new HashMap<String, Object>();
	                        /* DB-PAYMR-DDS */
	                        if (FileName.equals("DMPAYMR.DAT")){
	                        	
	                        	List<Map<String, Object>> payments = this.bankingFeedbackDao.queryP0028(str.substring(0, 2), str.substring(2, 16), str.substring(16, 32));	                            
	                        	if (str.substring(45, 46).equals("+")){
	                        	    map.put("AVBAL", Long.parseLong(str.substring(46, 57)));
	                        	}else{
	                        		map.put("AVBAL", Long.parseLong(str.substring(46, 57)) * -1);
	                        	}
	                            if (0 == payments.size()) {
	                            	/* 新增主檔 */
	                            	map.put("ITEMCD", str.substring(0, 2));
		                        	map.put("MRKEY", str.substring(2, 16));
		                        	/* 虛擬帳號 */
		                        	map.put("USERNO", str.substring(16, 32));
		                        	/* 異動日期 */
		                        	map.put("UPDATE_DATE", new Date());
	                            	this.bankingFeedbackDao.insertP0028_Master(map);
	                            }else{
	                            	/* 異動主檔 */
	                            	Map<String, Object> payment = payments.get(0);
	                            	this.bankingFeedbackDao.updateP0028_Master((Number) payment.get("P0028_MPK"),
	                            			                                   (Long) map.get("AVBAL"));
	                            }   
				            }
	                        /* DB-PAYDTLM-DDS */
	                        if (FileName.equals("DMPAYDTLM.DAT")){
	                        	try{
		                        	/* 新增明細 */
		                        	map.put("ITEMCD", str.substring(0, 2));
		                        	map.put("MRKEY", str.substring(2, 16));
		                        	/* 虛擬帳號 */
		                        	map.put("USERNO", str.substring(16, 32));
		                        	/* 交易日期 */
		                        	map.put("ADAY", str.substring(32, 40));
		                        	if (processDate.compareTo(str.substring(32, 40)) < 0){
		                        		processDate = str.substring(32, 40);
		                        	}		                        	
		                        	/* 交易時間 */
		                        	map.put("ATIME", str.substring(40, 48));
		                        	map.put("TBSDAY", str.substring(48, 56));
		                        	map.put("APTYPE", str.substring(56, 57));
		                        	map.put("TXNO", str.substring(57, 59));
		                        	map.put("DSCPT", str.substring(59, 62));
		                        	/* 沖正記號 */
		                        	map.put("HCODE", str.substring(62, 63));
		                        	/* 借貸別 */
		                        	map.put("CRDB", str.substring(63, 64));
		                        	/* 交易金額 */
	                        	 	map.put("TXAMT", str.substring(64, 75)); 	
		                        	/* 餘額  */
		                        	map.put("AVBAL", str.substring(75, 87));
		                        	map.put("ATMID", str.substring(87, 95));
		                        	map.put("KINBR", str.substring(95, 98));
		                        	map.put("TRMSEQ", str.substring(98, 100));
		                        	map.put("TXTNO", str.substring(100, 105));
		                        	map.put("TFRBK", str.substring(105, 108));
		                        	map.put("FL", str.substring(108, 109));
		                        	map.put("TFRACT", str.substring(109, 125));
		                        	map.put("STANBK", str.substring(125, 128));
		                        	map.put("STANSEQ", str.substring(128, 135));
		                        	/* 備註 */	                        	
		                        	map.put("MEMO", str.substring(135, str.length()).trim());
		                        	map.put("IMPORT_DATE", new Date());
		                        	if (StringUtils.isLong(str.substring(64, 75)) == true && 
		                        		StringUtils.isLong(str.substring(75, 87)) == true){
		                        	    this.bankingFeedbackDao.insertP0028_Detail(map);
		                        	}else{
		                        		logger.error("[錯誤]金額或餘額非數字{},{}", str.substring(64, 75), str.substring(75, 87));	
		                        	}
	                        	}catch (StringIndexOutOfBoundsException ex) {
	                        		logger.error("[字串]{}", str);
	                        		logger.error("[錯誤]有特殊符號無法解析");	                        		
	                        	}
				            }
	                        n = in.read(buffer, 0, BUFFER_SIZE);
	                        total++;
	                        /* 1000筆輸出一次Log */
	                        if (total % 1000 == 0) logger.info("count: {}", total);
	                    }
	                }catch (Exception ex) {
	                	logger.error("[字串]{}", str);
	                	logger.error("[錯誤]" + ex.toString(), ex);
	                }
	                finally { 
	                	/* 關閉檔案 */ 
	                    in.close();
	                }
	                /* 記錄筆數 */
	                if (FileName.equals("DMPAYMR.DAT")) logger.info("DMPAYMR 匯入資料筆數:{}", total);
	                if (FileName.equals("DMPAYDTLM.DAT")) logger.info("DMPAYDTLM 匯入資料筆數:{}", total);
	                
	                /* 連接FTP */
	                ftp.connect();
	                logger.info("{} is connect", host);
	                if (ftp.isConnected()){
	                	/* 切換FTP目錄  */
	                    if (remoteFolder != null && !remoteFolder.trim().equals("")){
	                        ftp.changeDirectory(remoteFolder);
	                        logger.info("Directory change to {}", ftp.getRemoteDirectory());
	                    }
	                	/* 已匯入完成原來源檔案改名 */	                   
		                ftp.rename(FileName, FileName.substring(0, FileName.length() - 3) +  StringUtils.GetStrCDate());
		                logger.info("{} is rename", FileName.substring(0, FileName.length() - 3) +  StringUtils.GetStrCDate());
	                }else{
	                	logger.error("{} is reconnect fail", host);
	                }
			    }
            }
        }
        catch (Exception ex) {
        	logger.error("[錯誤]" + ex.toString(), ex);
        }
        finally
        {
            if (null != ftp)
                try {
                    ftp.disconnect(true);
                }
                catch (Exception ex) {
                	logger.error("[錯誤]" + ex.toString(), ex);
                }
        }
    }
}
